package com.yst.web.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;


/**
 * json converter
 */
public class JsonConverter {

    private static final String DEFAULT_PATH_DELIMITER=".";

    private static final IJsonConverter defaultConverter=new IJsonConverter() {
        @Override
        public String toJSONString(Object object) {
            return JSON.toJSONString(object);
        }

        @Override
        public <T> T parseObject(String jsonString, Class<T> clazz) {
            return JSON.parseObject(jsonString,clazz);
        }

        @Override
        public <T> List<T> parseList(String jsonString, Class<T> elementClazz) {
            return JSON.parseArray(jsonString, elementClazz, JSONReader.Feature.AllowUnQuotedFieldNames);
        }
    };

    private static IJsonConverter converter;

    public static void setJsonConverter(IJsonConverter converter){
        JsonConverter.converter=converter;
    }

    /**
     * fetch a json converter,if not set converter,so use default converter
     * <p>
     *     default use fastjson2 depend product of the Alibaba open source
     * </p>
     * @return @see {@link IJsonConverter}
     */
    public static IJsonConverter getJsonConverter(){
        if (Objects.nonNull(converter)) {
            return converter;
        }
        else
        {
            return defaultConverter;
        }
    }

    /**
     * fetch value from expression of the path
     * @param jsonString string json
     * @param path expression of the path
     * @return value
     */
    public static String selectJsonValue(String jsonString,String path,String delimiter){
        JSONObject jsonObject=JSON.parseObject(jsonString);
        String[] keys=path.split(delimiter);
        List<String> pathKeys=new ArrayList<>(Arrays.asList(keys));
        if (pathKeys.isEmpty()){
            pathKeys.add(path);
        }
        for (String key:pathKeys){
            if (jsonObject.containsKey(key)){
                Object value=jsonObject.get(key);
                if (value instanceof JSONObject) {
                    jsonObject = jsonObject.getJSONObject(key);
                }
                else if (value instanceof String){
                    return (String)value;
                }
                else
                {
                    return JSON.toJSONString(value);
                }
            }
            else
            {
                throw new RuntimeException(String.format("json path error: path=%s json=%s at key position %s",
                        path,jsonString,key));
            }
        }
        return jsonObject.toString();
    }

    public static String selectJsonValue(String jsonString,String path){
        return selectJsonValue(jsonString,path,DEFAULT_PATH_DELIMITER);
    }

    public static <T> T selectJsonValueAs(String jsonString,String path,String delimiter,Class<T> clazz){
        return JSON.parseObject(selectJsonValue(jsonString,path,delimiter),clazz);
    }

    public static <T> T selectJsonValueAs(String jsonString,String path,Class<T> clazz){
        return JSON.parseObject(selectJsonValue(jsonString,path),clazz);
    }


    public interface IJsonConverter {
        String toJSONString(Object object);
        <T> T parseObject(String jsonString, Class<T> clazz);
        <T> List<T> parseList(String jsonString, Class<T> elementClazz);
    }
}
